By Dhanya Jagannathan

This is a reproducible RNotebook that entails the selection and initial processing of a gene expression dataset from an RNAseq experiment. More specifically, this notebook will (1) analyse information about the dataset I have chosen, and its associated publication, (2) map the expression data to HUGO gene symbols, (3) filter out unncecessary genes, and (4) normalize the dataset for downstream assignments that may potentially involve differential expression and pathway analyses. Note: sentences that are in bold answer the necessary questions from the assignment instructions.

Installing and Loading Packages

In the code block below, we install and load the necessary packages needed for the rest of the notebook.

#install BiocManager package 
if (!requireNamespace("BiocManager", quietly = TRUE))
    install.packages("BiocManager")

#install GEOquery
if (!requireNamespace("GEOquery", quietly = TRUE))
    BiocManager::install("GEOquery")
Setting options('download.file.method.GEOquery'='auto')
Setting options('GEOquery.inmemory.gpl'=FALSE)
#install knitr
if (!requireNamespace("knitr", quietly = TRUE))
    install.packages("knitr")

#install edgeR
if (!requireNamespace("edgeR", quietly = TRUE))
    BiocManager::install("edgeR")

#load up all of the libraries
library(GEOquery)
Loading required package: Biobase
Loading required package: BiocGenerics

Attaching package: 'BiocGenerics'
The following objects are masked from 'package:stats':

    IQR, mad, sd, var, xtabs
The following objects are masked from 'package:base':

    anyDuplicated, aperm, append, as.data.frame, basename, cbind,
    colnames, dirname, do.call, duplicated, eval, evalq, Filter, Find,
    get, grep, grepl, intersect, is.unsorted, lapply, Map, mapply,
    match, mget, order, paste, pmax, pmax.int, pmin, pmin.int,
    Position, rank, rbind, Reduce, rownames, sapply, setdiff, sort,
    table, tapply, union, unique, unsplit, which.max, which.min
Welcome to Bioconductor

    Vignettes contain introductory material; view with
    'browseVignettes()'. To cite Bioconductor, see
    'citation("Biobase")', and for packages 'citation("pkgname")'.
library(knitr)
library(biomaRt)
library(edgeR)
Loading required package: limma

Attaching package: 'limma'
The following object is masked from 'package:BiocGenerics':

    plotMA

Dataset Background Information

The expression dataset that I have selected is GSE221253, taken from the GEO expression data repository. The study associated with this dataset involved adoptive cell therapy. Adoptive cell therapy via tumor infiltrating lymphocytes (ACT-TIL) is a type of immunotherapy used to treat cancer. This study took samples from 13 patients having metastatic melanoma and performed RNAseq analysis, along with other analyses like spatial proteomics and scRNAseq, on tumor tissues before and after the cell therapy (pre- and post-ACT) in order to gain a better understanding of the interactions and cell states within the tumor microenvironment throughout treatment. For the RNAseq experiment, this resulted in a total of 26 samples, and 13 in each condition (two for each patient, and the experimental conditions being pre- and post-ACT treatment). I decided to choose this dataset because I am really interested in cell and gene therapies as well as synthetic biology. The field of editing cells ex-vivo, to cure various diseases is very interesting to me. The code block below gets and prints the summary information of my selected dataset.

#assign the dataset accession number to a variable for easy access. 
dataSetId <- "GSE221253"

#get dataset information from GEO, and display just the GEO description of the dataset. 
dataInfo <- getGEO(dataSetId, GSEMatrix = FALSE)
Reading file....
Parsing....
Found 27 entities...
GPL20301 (1 of 28 entities)
GSM6856978 (2 of 28 entities)
GSM6856979 (3 of 28 entities)
GSM6856980 (4 of 28 entities)
GSM6856981 (5 of 28 entities)
GSM6856982 (6 of 28 entities)
GSM6856983 (7 of 28 entities)
GSM6856984 (8 of 28 entities)
GSM6856985 (9 of 28 entities)
GSM6856986 (10 of 28 entities)
GSM6856987 (11 of 28 entities)
GSM6856988 (12 of 28 entities)
GSM6856989 (13 of 28 entities)
GSM6856990 (14 of 28 entities)
GSM6856991 (15 of 28 entities)
GSM6856992 (16 of 28 entities)
GSM6856993 (17 of 28 entities)
GSM6856994 (18 of 28 entities)
GSM6856995 (19 of 28 entities)
GSM6856996 (20 of 28 entities)
GSM6856997 (21 of 28 entities)
GSM6856998 (22 of 28 entities)
GSM6856999 (23 of 28 entities)
GSM6857000 (24 of 28 entities)
GSM6857001 (25 of 28 entities)
GSM6857002 (26 of 28 entities)
GSM6857003 (27 of 28 entities)
dataInfo@header$summary
[1] "Adoptive cell therapy (ACT) using ex vivo–expanded tumor-infiltrating lymphocytes (TILs) can eliminate or shrink metastatic melanoma, but its long-term efficacy remains limited to a fraction of patients. Using longitudinal samples from 13 patients with metastatic melanoma treated with TIL-ACT in a phase 1 clinical study, we interrogated cellular states within the tumor microenvironment (TME) and their interactions. We performed bulk and single-cell RNA sequencing, whole-exome sequencing, and spatial proteomic analyses in pre- and post-ACT tumor tissues, finding that ACT responders exhibited higher basal tumor cell–intrinsic immunogenicity and mutational burden. Compared with nonresponders, CD8+ TILs exhibited increased cytotoxicity, exhaustion, and costimulation, whereas myeloid cells had increased type I interferon signaling in responders. Cell-cell interaction prediction analyses corroborated by spatial neighborhood analyses revealed that responders had rich baseline intratumoral and stromal tumor–reactive T cell networks with activated myeloid populations. Successful TIL-ACT therapy further reprogrammed the myeloid compartment and increased TIL-myeloid networks. Our systematic target discovery study identifies potential T-myeloid cell network–based biomarkers that could improve patient selection and guide the design of ACT clinical trials."
Adoptive cell therapy (ACT) using ex vivo–expanded tumor-infiltrating lymphocytes (TILs) can eliminate or shrink metastatic melanoma, but its long-term efficacy remains limited to a fraction of patients. Using longitudinal samples from 13 patients with metastatic melanoma treated with TIL-ACT in a phase 1 clinical study, we interrogated cellular states within the tumor microenvironment (TME) and their interactions. We performed bulk and single-cell RNA sequencing, whole-exome sequencing, and spatial proteomic analyses in pre- and post-ACT tumor tissues, finding that ACT responders exhibited higher basal tumor cell–intrinsic immunogenicity and mutational burden. Compared with nonresponders, CD8+ TILs exhibited increased cytotoxicity, exhaustion, and costimulation, whereas myeloid cells had increased type I interferon signaling in responders. Cell-cell interaction prediction analyses corroborated by spatial neighborhood analyses revealed that responders had rich baseline intratumoral and stromal tumor–reactive T cell networks with activated myeloid populations. Successful TIL-ACT therapy further reprogrammed the myeloid compartment and increased TIL-myeloid networks. Our systematic target discovery study identifies potential T-myeloid cell network–based biomarkers that could improve patient selection and guide the design of ACT clinical trials.



Sometimes, we may even find information about the data and how it was processed. In the below code block, is some data processing information for the first sample in the list of samples used in this experiment. Usually, all the other samples in the experiment would entail the same processing steps as below. It is important to note that according to the below data processing information, the supplementary data file contains raw counts at the gene level, and that the counts have been mapped with HUGO Gene Symbols using the biomaRt package- this information may come in handy later on in this notebook when we attempt to map the expression data to HUGO Gene Symbols.

dataInfo@gsms[[1]]@header$data_processing
[1] "Illumina paired-end sequencing reads were aligned to the human reference GRCh37.75 genome using STAR aligner (version 2.6.0c) and the 2-pass method as briefly follows: the reads were aligned in a first round using the --runMode alignReads parameter, then a sample-specific splice-junction index was created using the --runMode genomeGenerate parameter. Finally, the reads were aligned using this newly created index as a reference. The number of counts was summarized at the gene level using htseq-count (version 0.9.1). The Ensembl ID were converted into gene symbols using the biomaRt package and only protein-coding, immunoglobulin and TCR genes were conserved for the analysis."
[2] "Assembly: GRCh37"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
[3] "Supplementary files format and content: Processed coding gene expression raw count with Gene Symbol mapping"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
Illumina paired-end sequencing reads were aligned to the human reference GRCh37.75 genome using STAR aligner (version 2.6.0c) and the 2-pass method as briefly follows: the reads were aligned in a first round using the --runMode alignReads parameter, then a sample-specific splice-junction index was created using the --runMode genomeGenerate parameter. Finally, the reads were aligned using this newly created index as a reference. The number of counts was summarized at the gene level using htseq-count (version 0.9.1). The Ensembl ID were converted into gene symbols using the biomaRt package and only protein-coding, immunoglobulin and TCR genes were conserved for the analysis.

Assembly: GRCh37

Supplementary files format and content: Processed coding gene expression raw count with Gene Symbol mapping

Information on Dataset Samples

Now that we have an understanding of the dataset and the associated experiment, it is helpful to have information about each of our samples nice and handy in a table. Sample information involves the sample accession ID, the ID of the patient it came from, tissue it was taken from, and whether it was taken pre- or post- ACT treatment. The below code block consolidates all of this information, and the code block after cleans up and formats this information into a nice table to view in html format (third code block).

# Consolidation of sample information
sampleList <- dataInfo@gsms

samplesInfo <- do.call(rbind,
                        lapply(sampleList, 
                               FUN=function(x){
                                 c(x@header$title, 
                                   x@header$characteristics_ch1[1],
                                   x@header$characteristics_ch1[3])
                               }))
#Neatly format above data. 
colnames(samplesInfo) <- c("title", "tissue", "time")
samplesInfo[,'tissue'] <- gsub(samplesInfo[,'tissue'],
                                pattern = "tissue: ", 
                                replacement = "")
samplesInfo[,'time'] <- gsub(samplesInfo[,'time'],
                                pattern = "time: ", 
                                replacement = "")



From the snippet of the sample data below (for the first five samples), we are able to visualize the two different conditions mentioned at the beginnings of this rnotebook: each patient constitutes two samples (one taken at pre-ACT, and another taken after ACT). This table also show additional sample information like what kind of tissue the samples came from. All the information in each of the columns is pretty self explanatory, so no additional information digging was needed in this case to fill up any data plotholes.This experiment contains 13 biological replicates (13 patients). I am also not quite sure whether there are technical replicates associated with this experiment, and don’t know how to handle that quite yet

kable(samplesInfo[1:5,], format = "html")
title tissue time
GSM6856978 patient1_preACT_1 melanoma pre-ACT
GSM6856979 patient1_postACT_1 melanoma post-ACT
GSM6856980 patient2_preACT_1 melanoma pre-ACT
GSM6856981 patient2_postACT_1 melanoma post-ACT
GSM6856982 patient3_preACT_1 melanoma pre-ACT

Downloading the Data

Now that we have thoroughly analysed the sample information, we need to actually obtain the gene expression counts data. We first look at what supplementary files exist associated with the experiment. There is only one data file associated with this experiment, and from the previous code block where we displayed data processing information, it mentioned “Supplementary files format and content: Processed coding gene expression raw count with Gene Symbol mapping” which seems to be exactly the file we need. However, we need to verify this just in case and make sure that this file contains ALL gene counts, and not just a small subset. The code block below just displays the file name, and the subsequent blocks actually download this data text file, and verify that this is indeed the correct data file.

supplementary_files = getGEOSuppFiles(dataSetId, fetch_files = FALSE)
supplementary_files[[1]] 
[1] "GSE221253_X_Gene_Count.txt.gz"
GSE221253_X_Gene_Count.txt.gz



Rather than re-downloading the gene counts data file everytime this notebook is run, we only download it when necessary. To do this, we go through all of the supplementary data files available, and apply a function to each of them that determines whether they exist in the directory (provided path) or not. Only the files that are not present in our specified directory are stored in ‘missing_files’, and thus downloaded.

# store the path you want to download the data file in, in a variable. 
directory <- file.path(getwd())

missing <- supplementary_files[[1]][!unlist(
  lapply(supplementary_files[[1]], FUN=function(x) {
    file.exists(
      file.path(directory, dataSetId, x)
    )
  })
)]

# download the missing supplementary file
if(length(missing) == 1) {
  #get supp file
  supp_files = getGEOSuppFiles(dataSetId, 
                            filter_regex = missing[1], 
                            baseDir = directory, 
                            fetch_files = TRUE)
}



Here, we read in the raw gene counts file, and verify that it is indeed the correct file, since it has ~20000 genes and 26 samples (13 pre-ACT and 13 post-ACT), which is what we expect.

#read in the downloaded data into a table, ACT_vs_baseline. 
ACT_vs_baseline <- read.table(
  file.path(directory, dataSetId, supplementary_files[[1]]),
           header=TRUE, 
           check.names=TRUE
)
dim(ACT_vs_baseline)
[1] 19117    26



We also ensure that all of the genes and samples are unique and there are no null values for genes

#unique samples!
length(unique(colnames(ACT_vs_baseline))) == 26
[1] TRUE
#unique genes!
length(unique(rownames(ACT_vs_baseline))) == 19117
[1] TRUE
#no null rows names!
length(!is.na(rownames(ACT_vs_baseline))) == 19117
[1] TRUE



Here, we visualize the downloaded gene counts data table, for a small subset of the data (5 genes and 2 samples from one patient).

#Visualize subset of the data. 
#data makes perfect sense! Thanks authors!
ACT_vs_baseline[1:5, 1:2]

Mapping to HUGO Gene Symbols

According to the output of one of the previous code blocks above in the “Dataset Background Information” section, as well as by just inspecting the above subset of data, our gene expression data has already been mapped to HUGO symbols. However, it still may be of interest to re-map the rownames to HUGO symbols ourselves to see if there are any rows in our data that cannot be mapped to HUGO gene symbols. The following code blocks connect to bioMart, and create a conversion file for mapping our current gene symbols to HUGO gene symbols.

#connect to mart + use the human dataset.
ensembl <- useMart("ensembl")
ensembl = useDataset("hsapiens_gene_ensembl", mart=ensembl)
convertIds <- rownames(ACT_vs_baseline)

#check to see if conversion file exists, if not, create it. 
conversion_stash <- "id_conversion.rds"
if(file.exists(conversion_stash)) {
  id_conversion <- readRDS(conversion_stash)
} else {
  # attributes refers to: what identifier type we want (in this case "hgnc_symbol")
  # filters refers to: what we will filter results by, which is just "hgnc_symbol"
  # values refers to: "hgnc_symbol" (What we have as rownames so far)
  id_conversion <- getBM(attributes = c("hgnc_symbol"), 
                         filters = c("hgnc_symbol"), 
                         values = convertIds, 
                         mart = ensembl)
  saveRDS(id_conversion, conversion_stash)
}



Here, we output statistics: (1) the number of genes from our original gene counts table that were mapped to actual HUGO symbols, (2) How many genes did we begin with in our original table, and (3) The difference between (1) and (2). From these results, we see that 940 genes from our original gene expression table were unable to be mapped to HUGO gene symbols. This is actually not that bad! In addition, there does not seem to be expression values that were not unique for specific genes.

#how many genes from our original gene symbol rownames were mapped to actual HUGO symbols? 
length(which(rownames(ACT_vs_baseline) %in%
               id_conversion$hgnc_symbol))
[1] 18177
#Out of our total genes that we started with: 
nrow(ACT_vs_baseline)
[1] 19117
# Calculate the difference between the number of rows originally and then number of rownames that were able to be mapped to HUGO symbols. 
differenceMap <- nrow(ACT_vs_baseline) - length(which(rownames(ACT_vs_baseline) %in% id_conversion$hgnc_symbol))

differenceMap
[1] 940



This code block just shows the first 10 gene names (from the 940 count above) that were unable to be mapped to HUGO gene symbols.

rownames(ACT_vs_baseline)[!(rownames(ACT_vs_baseline) %in% id_conversion$hgnc_symbol)][1:10]
 [1] "HIST1H1B"  "HIST1H4C"  "MTRNR2L12" "HIST1H2AI" "HIST1H2BL" "HIST3H2BB"
 [7] "NOV"       "HIST1H1D"  "HIST3H2A"  "FAM166B"  
HIST1H1B

HIST1H4C

MTRNR2L12

HIST1H2AI

HIST1H2BL

HIST3H2BB

NOV

HIST1H1D

HIST3H2A

FAM166B



In this code block here, I decided to merge both the id_conversion data frame (with the actual HUGO gene symbols) and the original ACT_vs_baseline gene expression data frame. The resulting dataframe still keeps the rows that were unable to be mapped to HUGO gene symbols, since these genes could potentially constitute an uncharacterized signal later on in the rest of the assignments (when performing Differential Expression and Pathway analyses).

ACT_vs_baseline_annot <- merge(id_conversion, ACT_vs_baseline, by.x = 1, by.y = 0, all.y = TRUE)

rownames(ACT_vs_baseline_annot) <- ACT_vs_baseline_annot$hgnc_symbol
ACT_vs_baseline_annot <- ACT_vs_baseline_annot[-c(1)]

# our current gene counts data table (with mapping completed)
ACT_vs_baseline_annot[1:10, 1:2]

Dataset Filteration and Normalization

Now that we have the gene expression counts table with HUGO gene symbol mappings, the next step is to filter out the genes with low counts and normalize our data. Filtering ensures that there is less noise in the data, and statistical calculations are less computationally intensive down the line (since we will have less genes). Sample based normalization ensures to adjust for variations in the data and also allows for between sample comparisons. The first code block outputs a density plot of the gene expression data BEFORE filtration and normalization. The next couple of code blocks after, filters out the genes with low counts, and performs TMM normalization.

# density graph pre filtering + pre normalization
counts_density <- apply(log2(ACT_vs_baseline_annot), 2, density)
xlim <- 0; ylim <- 0
for (i in 1:length(counts_density)) {
  xlim <- range(c(xlim, counts_density[[i]]$x));
  ylim <- range(c(ylim, counts_density[[i]]$y))
}

cols <- (length(counts_density))
ltys <- rep(1, length(counts_density))

#plot 
plot(counts_density[[1]], xlim=xlim, ylim=ylim, type="n", 
     ylab="Smoothing density of log2-CPM", 
     main="", cex.lab = 0.85)

for(i in 1:length(counts_density))
  lines(counts_density[[i]], cols=cols[i], lty=ltys[i])
Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

We see here that the filteration of outlier genes with low gene counts, removed 3678 genes from our expression dataset

# set the minimum number of samples
min_samples <- 3

data_as_matrix <- as.matrix(ACT_vs_baseline_annot)

# Filter out low counts
keep <- rowSums(cpm(data_as_matrix) > 1) >= min_samples
data_filtered <- data_as_matrix[keep,]
nrow(data_filtered)
[1] 15439
#Total number of genes removed: 
nrow(ACT_vs_baseline_annot) - nrow(data_filtered)
[1] 3678
# TMM Normalization 
dge_list = DGEList(counts = data_filtered)
dge_list = calcNormFactors(dge_list)
normalized_counts <- cpm(dge_list)
normalized_counts <- as.data.frame(normalized_counts)

normalized_counts



This code block outputs a density plot of the gene expression data after filtration and normalization. Comparing the two plots (pre- and post- filteration + normalization), shows the changes in the data, uniform and less noisy.

#post-filtering + post normalization: 

counts_density <- apply(log2(normalized_counts), 2, density)
xlim <- 0; ylim <- 0
for (i in 1:length(counts_density)) {
  xlim <- range(c(xlim, counts_density[[i]]$x));
  ylim <- range(c(ylim, counts_density[[i]]$y))
}

cols <- (length(counts_density))
ltys <- rep(1, length(counts_density))

#plot 
plot(counts_density[[1]], xlim=xlim, ylim=ylim, type="n", 
     ylab="Smoothing density of log2-CPM", 
     main="", cex.lab = 0.85)

for(i in 1:length(counts_density))
  lines(counts_density[[i]], cols=cols[i], lty=ltys[i])
Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter

Warning in plot.xy(xy.coords(x, y), type = type, ...): "cols" is not a
graphical parameter



The last step of this notebook is to export out our fully processed (mapped, filtered, and normalized) gene expression dataframe to a txt file for downstream use in future assignments! In regards to the final coverage of my dataset, the end product is a dataframe with 15439 HUGO mapped genes and counts for each

write.table(normalized_counts, file.path(getwd(),"normalized_baseline_vs_TIL_counts.txt"), quote = FALSE, sep = "\t", row.names = TRUE)

References

Morgan M, Ramos M (2023). BiocManager: Access the Bioconductor Project Package Repository. R package version 1.30.22, https://CRAN.R-project.org/package=BiocManager.

Davis, S. and Meltzer, P. S. GEOquery: a bridge between the Gene Expression Omnibus (GEO) and BioConductor. Bioinformatics, 2007, 14, 1846-1847

Xie Y (2023). knitr: A General-Purpose Package for Dynamic Report Generation in R. R package version 1.45, https://yihui.org/knitr/.

Robinson MD, McCarthy DJ and Smyth GK (2010). edgeR: a Bioconductor package for differential expression analysis of digital gene expression data. Bioinformatics 26, 139-140

Response to tumor-infiltrating lymphocyte adoptive therapy is associated with preexisting CD8+ T-myeloid cell … (n.d.). https://www.science.org/doi/10.1126/sciimmunol.adg7995

LS0tCnRpdGxlOiAiQkNCNDIwIEFzc2lnbm1lbnQgMTogRGF0YXNldCBTZWxlY3Rpb24gKyBJbml0aWFsIFByb2Nlc3NpbmciCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KIyMgQnkgRGhhbnlhIEphZ2FubmF0aGFuIAoKVGhpcyBpcyBhIHJlcHJvZHVjaWJsZSBSTm90ZWJvb2sgdGhhdCBlbnRhaWxzIHRoZSBzZWxlY3Rpb24gYW5kIGluaXRpYWwgcHJvY2Vzc2luZyBvZiBhIGdlbmUgZXhwcmVzc2lvbiBkYXRhc2V0IGZyb20gYW4gUk5Bc2VxIGV4cGVyaW1lbnQuIE1vcmUgc3BlY2lmaWNhbGx5LCB0aGlzIG5vdGVib29rIHdpbGwgKDEpIGFuYWx5c2UgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGRhdGFzZXQgSSBoYXZlIGNob3NlbiwgYW5kIGl0cyBhc3NvY2lhdGVkIHB1YmxpY2F0aW9uLCAoMikgbWFwIHRoZSBleHByZXNzaW9uIGRhdGEgdG8gSFVHTyBnZW5lIHN5bWJvbHMsICgzKSBmaWx0ZXIgb3V0IHVubmNlY2Vzc2FyeSBnZW5lcywgYW5kICg0KSBub3JtYWxpemUgdGhlIGRhdGFzZXQgZm9yIGRvd25zdHJlYW0gYXNzaWdubWVudHMgdGhhdCBtYXkgcG90ZW50aWFsbHkgaW52b2x2ZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmQgcGF0aHdheSBhbmFseXNlcy4gTm90ZTogc2VudGVuY2VzIHRoYXQgYXJlIGluICoqYm9sZCoqIGFuc3dlciB0aGUgbmVjZXNzYXJ5IHF1ZXN0aW9ucyBmcm9tIHRoZSBhc3NpZ25tZW50IGluc3RydWN0aW9ucy4gCgoKIyMjIEluc3RhbGxpbmcgYW5kIExvYWRpbmcgUGFja2FnZXMKSW4gdGhlIGNvZGUgYmxvY2sgYmVsb3csIHdlIGluc3RhbGwgYW5kIGxvYWQgdGhlIG5lY2Vzc2FyeSBwYWNrYWdlcyBuZWVkZWQgZm9yIHRoZSByZXN0IG9mIHRoZSBub3RlYm9vay4gCmBgYHtyfQoKI2luc3RhbGwgQmlvY01hbmFnZXIgcGFja2FnZSAKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJCaW9jTWFuYWdlciIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIikKCiNpbnN0YWxsIEdFT3F1ZXJ5CmlmICghcmVxdWlyZU5hbWVzcGFjZSgiR0VPcXVlcnkiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiR0VPcXVlcnkiKQoKI2luc3RhbGwga25pdHIKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJrbml0ciIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikKCiNpbnN0YWxsIGVkZ2VSCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZWRnZVIiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiZWRnZVIiKQoKI2xvYWQgdXAgYWxsIG9mIHRoZSBsaWJyYXJpZXMKbGlicmFyeShHRU9xdWVyeSkKbGlicmFyeShrbml0cikKbGlicmFyeShiaW9tYVJ0KQpsaWJyYXJ5KGVkZ2VSKQoKYGBgCgojIyMgRGF0YXNldCBCYWNrZ3JvdW5kIEluZm9ybWF0aW9uClRoZSBleHByZXNzaW9uIGRhdGFzZXQgdGhhdCBJIGhhdmUgc2VsZWN0ZWQgaXMgW0dTRTIyMTI1M10oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9nZW8vcXVlcnkvYWNjLmNnaT9hY2M9R1NFMjIxMjUzKSwgdGFrZW4gZnJvbSB0aGUgR0VPIGV4cHJlc3Npb24gZGF0YSByZXBvc2l0b3J5LiBUaGUgc3R1ZHkgYXNzb2NpYXRlZCB3aXRoIHRoaXMgZGF0YXNldCBpbnZvbHZlZCBhZG9wdGl2ZSBjZWxsIHRoZXJhcHkuIEFkb3B0aXZlIGNlbGwgdGhlcmFweSB2aWEgdHVtb3IgaW5maWx0cmF0aW5nIGx5bXBob2N5dGVzIChBQ1QtVElMKSBpcyBhIHR5cGUgb2YgaW1tdW5vdGhlcmFweSB1c2VkIHRvIHRyZWF0IGNhbmNlci4gVGhpcyBbc3R1ZHldKGh0dHBzOi8vd3d3LnNjaWVuY2Uub3JnL2RvaS8xMC4xMTI2L3NjaWltbXVub2wuYWRnNzk5NSkgdG9vayBzYW1wbGVzIGZyb20gMTMgcGF0aWVudHMgaGF2aW5nIG1ldGFzdGF0aWMgbWVsYW5vbWEgYW5kIHBlcmZvcm1lZCBSTkFzZXEgYW5hbHlzaXMsIGFsb25nIHdpdGggb3RoZXIgYW5hbHlzZXMgbGlrZSBzcGF0aWFsIHByb3Rlb21pY3MgYW5kIHNjUk5Bc2VxLCBvbiB0dW1vciB0aXNzdWVzIGJlZm9yZSBhbmQgYWZ0ZXIgdGhlIGNlbGwgdGhlcmFweSAocHJlLSBhbmQgcG9zdC1BQ1QpIGluIG9yZGVyIHRvIGdhaW4gYSBiZXR0ZXIgdW5kZXJzdGFuZGluZyBvZiB0aGUgaW50ZXJhY3Rpb25zIGFuZCBjZWxsIHN0YXRlcyB3aXRoaW4gdGhlIHR1bW9yIG1pY3JvZW52aXJvbm1lbnQgdGhyb3VnaG91dCB0cmVhdG1lbnQuICoqRm9yIHRoZSBSTkFzZXEgZXhwZXJpbWVudCwgdGhpcyByZXN1bHRlZCBpbiBhIHRvdGFsIG9mIDI2IHNhbXBsZXMsIGFuZCAxMyBpbiBlYWNoIGNvbmRpdGlvbioqICh0d28gZm9yIGVhY2ggcGF0aWVudCwgYW5kIHRoZSBleHBlcmltZW50YWwgY29uZGl0aW9ucyBiZWluZyBwcmUtIGFuZCBwb3N0LUFDVCB0cmVhdG1lbnQpLiAqKkkgZGVjaWRlZCB0byBjaG9vc2UgdGhpcyBkYXRhc2V0IGJlY2F1c2UgSSBhbSByZWFsbHkgaW50ZXJlc3RlZCBpbiBjZWxsIGFuZCBnZW5lIHRoZXJhcGllcyBhcyB3ZWxsIGFzIHN5bnRoZXRpYyBiaW9sb2d5LiBUaGUgZmllbGQgb2YgZWRpdGluZyBjZWxscyBleC12aXZvLCB0byBjdXJlIHZhcmlvdXMgZGlzZWFzZXMgaXMgdmVyeSBpbnRlcmVzdGluZyB0byBtZS4qKiBUaGUgY29kZSBibG9jayBiZWxvdyBnZXRzIGFuZCBwcmludHMgdGhlIHN1bW1hcnkgaW5mb3JtYXRpb24gb2YgbXkgc2VsZWN0ZWQgZGF0YXNldC4gCgpgYGB7cn0KI2Fzc2lnbiB0aGUgZGF0YXNldCBhY2Nlc3Npb24gbnVtYmVyIHRvIGEgdmFyaWFibGUgZm9yIGVhc3kgYWNjZXNzLiAKZGF0YVNldElkIDwtICJHU0UyMjEyNTMiCgojZ2V0IGRhdGFzZXQgaW5mb3JtYXRpb24gZnJvbSBHRU8sIGFuZCBkaXNwbGF5IGp1c3QgdGhlIEdFTyBkZXNjcmlwdGlvbiBvZiB0aGUgZGF0YXNldC4gCmRhdGFJbmZvIDwtIGdldEdFTyhkYXRhU2V0SWQsIEdTRU1hdHJpeCA9IEZBTFNFKQpkYXRhSW5mb0BoZWFkZXIkc3VtbWFyeQoKYGBgCgo8YnI+Cjxicj4KU29tZXRpbWVzLCB3ZSBtYXkgZXZlbiBmaW5kIGluZm9ybWF0aW9uIGFib3V0IHRoZSBkYXRhIGFuZCBob3cgaXQgd2FzIHByb2Nlc3NlZC4gSW4gdGhlIGJlbG93IGNvZGUgYmxvY2ssIGlzIHNvbWUgZGF0YSBwcm9jZXNzaW5nIGluZm9ybWF0aW9uIGZvciB0aGUgZmlyc3Qgc2FtcGxlIGluIHRoZSBsaXN0IG9mIHNhbXBsZXMgdXNlZCBpbiB0aGlzIGV4cGVyaW1lbnQuIFVzdWFsbHksIGFsbCB0aGUgb3RoZXIgc2FtcGxlcyBpbiB0aGUgZXhwZXJpbWVudCB3b3VsZCBlbnRhaWwgdGhlIHNhbWUgcHJvY2Vzc2luZyBzdGVwcyBhcyBiZWxvdy4gCkl0IGlzIGltcG9ydGFudCB0byBub3RlIHRoYXQgYWNjb3JkaW5nIHRvIHRoZSBiZWxvdyBkYXRhIHByb2Nlc3NpbmcgaW5mb3JtYXRpb24sIHRoZSBzdXBwbGVtZW50YXJ5IGRhdGEgZmlsZSBjb250YWlucyByYXcgY291bnRzIGF0IHRoZSBnZW5lIGxldmVsLCBhbmQgdGhhdCB0aGUgY291bnRzIGhhdmUgYmVlbiBtYXBwZWQgd2l0aCBIVUdPIEdlbmUgU3ltYm9scyB1c2luZyB0aGUgYmlvbWFSdCBwYWNrYWdlLSB0aGlzIGluZm9ybWF0aW9uIG1heSBjb21lIGluIGhhbmR5IGxhdGVyIG9uIGluIHRoaXMgbm90ZWJvb2sgd2hlbiB3ZSBhdHRlbXB0IHRvIG1hcCB0aGUgZXhwcmVzc2lvbiBkYXRhIHRvIEhVR08gR2VuZSBTeW1ib2xzLiAKYGBge3J9CmRhdGFJbmZvQGdzbXNbWzFdXUBoZWFkZXIkZGF0YV9wcm9jZXNzaW5nCmBgYAoKCgojIyMgSW5mb3JtYXRpb24gb24gRGF0YXNldCBTYW1wbGVzIApOb3cgdGhhdCB3ZSBoYXZlIGFuIHVuZGVyc3RhbmRpbmcgb2YgdGhlIGRhdGFzZXQgYW5kIHRoZSBhc3NvY2lhdGVkIGV4cGVyaW1lbnQsIGl0IGlzIGhlbHBmdWwgdG8gaGF2ZSBpbmZvcm1hdGlvbiBhYm91dCBlYWNoIG9mIG91ciBzYW1wbGVzIG5pY2UgYW5kIGhhbmR5IGluIGEgdGFibGUuIFNhbXBsZSBpbmZvcm1hdGlvbiBpbnZvbHZlcyB0aGUgc2FtcGxlIGFjY2Vzc2lvbiBJRCwgdGhlIElEIG9mIHRoZSBwYXRpZW50IGl0IGNhbWUgZnJvbSwgdGlzc3VlIGl0IHdhcyB0YWtlbiBmcm9tLCBhbmQgd2hldGhlciBpdCB3YXMgdGFrZW4gcHJlLSBvciBwb3N0LSBBQ1QgdHJlYXRtZW50LiBUaGUgYmVsb3cgY29kZSBibG9jayBjb25zb2xpZGF0ZXMgYWxsIG9mIHRoaXMgaW5mb3JtYXRpb24sIGFuZCB0aGUgY29kZSBibG9jayBhZnRlciBjbGVhbnMgdXAgYW5kIGZvcm1hdHMgdGhpcyBpbmZvcm1hdGlvbiBpbnRvIGEgbmljZSB0YWJsZSB0byB2aWV3IGluIGh0bWwgZm9ybWF0ICh0aGlyZCBjb2RlIGJsb2NrKS4gCmBgYHtyfQojIENvbnNvbGlkYXRpb24gb2Ygc2FtcGxlIGluZm9ybWF0aW9uCnNhbXBsZUxpc3QgPC0gZGF0YUluZm9AZ3NtcwoKc2FtcGxlc0luZm8gPC0gZG8uY2FsbChyYmluZCwKICAgICAgICAgICAgICAgICAgICAgICAgbGFwcGx5KHNhbXBsZUxpc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOPWZ1bmN0aW9uKHgpewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKHhAaGVhZGVyJHRpdGxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4QGhlYWRlciRjaGFyYWN0ZXJpc3RpY3NfY2gxWzFdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhAaGVhZGVyJGNoYXJhY3RlcmlzdGljc19jaDFbM10pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSkKYGBgCgpgYGB7cn0KCiNOZWF0bHkgZm9ybWF0IGFib3ZlIGRhdGEuIApjb2xuYW1lcyhzYW1wbGVzSW5mbykgPC0gYygidGl0bGUiLCAidGlzc3VlIiwgInRpbWUiKQpzYW1wbGVzSW5mb1ssJ3Rpc3N1ZSddIDwtIGdzdWIoc2FtcGxlc0luZm9bLCd0aXNzdWUnXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gInRpc3N1ZTogIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGFjZW1lbnQgPSAiIikKc2FtcGxlc0luZm9bLCd0aW1lJ10gPC0gZ3N1YihzYW1wbGVzSW5mb1ssJ3RpbWUnXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gInRpbWU6ICIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxhY2VtZW50ID0gIiIpCgoKYGBgCgo8YnI+Cjxicj4KRnJvbSB0aGUgc25pcHBldCBvZiB0aGUgc2FtcGxlIGRhdGEgYmVsb3cgKGZvciB0aGUgZmlyc3QgZml2ZSBzYW1wbGVzKSwgd2UgYXJlIGFibGUgdG8gdmlzdWFsaXplIHRoZSB0d28gZGlmZmVyZW50IGNvbmRpdGlvbnMgbWVudGlvbmVkIGF0IHRoZSBiZWdpbm5pbmdzIG9mIHRoaXMgcm5vdGVib29rOiBlYWNoIHBhdGllbnQgY29uc3RpdHV0ZXMgdHdvIHNhbXBsZXMgKG9uZSB0YWtlbiBhdCBwcmUtQUNULCBhbmQgYW5vdGhlciB0YWtlbiBhZnRlciBBQ1QpLiBUaGlzIHRhYmxlIGFsc28gc2hvdyBhZGRpdGlvbmFsIHNhbXBsZSBpbmZvcm1hdGlvbiBsaWtlIHdoYXQga2luZCBvZiB0aXNzdWUgdGhlIHNhbXBsZXMgY2FtZSBmcm9tLiBBbGwgdGhlIGluZm9ybWF0aW9uIGluIGVhY2ggb2YgdGhlIGNvbHVtbnMgaXMgcHJldHR5IHNlbGYgZXhwbGFuYXRvcnksIHNvIG5vIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gZGlnZ2luZyB3YXMgbmVlZGVkIGluIHRoaXMgY2FzZSB0byBmaWxsIHVwIGFueSBkYXRhIHBsb3Rob2xlcy4qKlRoaXMgZXhwZXJpbWVudCBjb250YWlucyAxMyBiaW9sb2dpY2FsIHJlcGxpY2F0ZXMgKDEzIHBhdGllbnRzKS4gSSBhbSBhbHNvIG5vdCBxdWl0ZSBzdXJlIHdoZXRoZXIgdGhlcmUgYXJlIHRlY2huaWNhbCByZXBsaWNhdGVzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGV4cGVyaW1lbnQsIGFuZCBkb24ndCBrbm93IGhvdyB0byBoYW5kbGUgdGhhdCBxdWl0ZSB5ZXQqKgpgYGB7cn0Ka2FibGUoc2FtcGxlc0luZm9bMTo1LF0sIGZvcm1hdCA9ICJodG1sIikKYGBgCgoKCiMjIyBEb3dubG9hZGluZyB0aGUgRGF0YQpOb3cgdGhhdCB3ZSBoYXZlIHRob3JvdWdobHkgYW5hbHlzZWQgdGhlIHNhbXBsZSBpbmZvcm1hdGlvbiwgd2UgbmVlZCB0byBhY3R1YWxseSBvYnRhaW4gdGhlIGdlbmUgZXhwcmVzc2lvbiBjb3VudHMgZGF0YS4gV2UgZmlyc3QgbG9vayBhdCB3aGF0IHN1cHBsZW1lbnRhcnkgZmlsZXMgZXhpc3QgYXNzb2NpYXRlZCB3aXRoIHRoZSBleHBlcmltZW50LiAKVGhlcmUgaXMgb25seSBvbmUgZGF0YSBmaWxlIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGV4cGVyaW1lbnQsIGFuZCBmcm9tIHRoZSBwcmV2aW91cyBjb2RlIGJsb2NrIHdoZXJlIHdlIGRpc3BsYXllZCBkYXRhIHByb2Nlc3NpbmcgaW5mb3JtYXRpb24sIGl0IG1lbnRpb25lZCAiU3VwcGxlbWVudGFyeSBmaWxlcyBmb3JtYXQgYW5kIGNvbnRlbnQ6IFByb2Nlc3NlZCBjb2RpbmcgZ2VuZSBleHByZXNzaW9uIHJhdyBjb3VudCB3aXRoIEdlbmUgU3ltYm9sIG1hcHBpbmciIHdoaWNoIHNlZW1zIHRvIGJlIGV4YWN0bHkgdGhlIGZpbGUgd2UgbmVlZC4gCkhvd2V2ZXIsIHdlIG5lZWQgdG8gdmVyaWZ5IHRoaXMganVzdCBpbiBjYXNlIGFuZCBtYWtlIHN1cmUgdGhhdCB0aGlzIGZpbGUgY29udGFpbnMgQUxMIGdlbmUgY291bnRzLCBhbmQgbm90IGp1c3QgYSBzbWFsbCBzdWJzZXQuIFRoZSBjb2RlIGJsb2NrIGJlbG93IGp1c3QgZGlzcGxheXMgdGhlIGZpbGUgbmFtZSwgYW5kIHRoZSBzdWJzZXF1ZW50IGJsb2NrcyBhY3R1YWxseSBkb3dubG9hZCB0aGlzIGRhdGEgdGV4dCBmaWxlLCBhbmQgdmVyaWZ5IHRoYXQgdGhpcyBpcyBpbmRlZWQgdGhlIGNvcnJlY3QgZGF0YSBmaWxlLiAKYGBge3J9CnN1cHBsZW1lbnRhcnlfZmlsZXMgPSBnZXRHRU9TdXBwRmlsZXMoZGF0YVNldElkLCBmZXRjaF9maWxlcyA9IEZBTFNFKQpzdXBwbGVtZW50YXJ5X2ZpbGVzW1sxXV0gCmBgYAo8YnI+Cjxicj4KUmF0aGVyIHRoYW4gcmUtZG93bmxvYWRpbmcgdGhlIGdlbmUgY291bnRzIGRhdGEgZmlsZSBldmVyeXRpbWUgdGhpcyBub3RlYm9vayBpcyBydW4sIHdlIG9ubHkgZG93bmxvYWQgaXQgd2hlbiBuZWNlc3NhcnkuIFRvIGRvIHRoaXMsIHdlIGdvIHRocm91Z2ggYWxsIG9mIHRoZSBzdXBwbGVtZW50YXJ5IGRhdGEgZmlsZXMgYXZhaWxhYmxlLCBhbmQgYXBwbHkgYSBmdW5jdGlvbiB0byBlYWNoIG9mIHRoZW0gdGhhdCBkZXRlcm1pbmVzIHdoZXRoZXIgdGhleSBleGlzdCBpbiB0aGUgZGlyZWN0b3J5IChwcm92aWRlZCBwYXRoKSBvciBub3QuIE9ubHkgdGhlIGZpbGVzIHRoYXQgYXJlIG5vdCBwcmVzZW50IGluIG91ciBzcGVjaWZpZWQgZGlyZWN0b3J5IGFyZSBzdG9yZWQgaW4gJ21pc3NpbmdfZmlsZXMnLCBhbmQgdGh1cyBkb3dubG9hZGVkLiAKYGBge3J9CgoKIyBzdG9yZSB0aGUgcGF0aCB5b3Ugd2FudCB0byBkb3dubG9hZCB0aGUgZGF0YSBmaWxlIGluLCBpbiBhIHZhcmlhYmxlLiAKZGlyZWN0b3J5IDwtIGZpbGUucGF0aChnZXR3ZCgpKQoKbWlzc2luZyA8LSBzdXBwbGVtZW50YXJ5X2ZpbGVzW1sxXV1bIXVubGlzdCgKICBsYXBwbHkoc3VwcGxlbWVudGFyeV9maWxlc1tbMV1dLCBGVU49ZnVuY3Rpb24oeCkgewogICAgZmlsZS5leGlzdHMoCiAgICAgIGZpbGUucGF0aChkaXJlY3RvcnksIGRhdGFTZXRJZCwgeCkKICAgICkKICB9KQopXQoKIyBkb3dubG9hZCB0aGUgbWlzc2luZyBzdXBwbGVtZW50YXJ5IGZpbGUKaWYobGVuZ3RoKG1pc3NpbmcpID09IDEpIHsKICAjZ2V0IHN1cHAgZmlsZQogIHN1cHBfZmlsZXMgPSBnZXRHRU9TdXBwRmlsZXMoZGF0YVNldElkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcl9yZWdleCA9IG1pc3NpbmdbMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFzZURpciA9IGRpcmVjdG9yeSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZXRjaF9maWxlcyA9IFRSVUUpCn0KCgpgYGAKPGJyPgo8YnI+CkhlcmUsIHdlIHJlYWQgaW4gdGhlIHJhdyBnZW5lIGNvdW50cyBmaWxlLCBhbmQgdmVyaWZ5IHRoYXQgaXQgaXMgaW5kZWVkIHRoZSBjb3JyZWN0IGZpbGUsIHNpbmNlIGl0IGhhcyB+MjAwMDAgZ2VuZXMgYW5kIDI2IHNhbXBsZXMgKDEzIHByZS1BQ1QgYW5kIDEzIHBvc3QtQUNUKSwgd2hpY2ggaXMgd2hhdCB3ZSBleHBlY3QuIApgYGB7cn0KCiNyZWFkIGluIHRoZSBkb3dubG9hZGVkIGRhdGEgaW50byBhIHRhYmxlLCBBQ1RfdnNfYmFzZWxpbmUuIApBQ1RfdnNfYmFzZWxpbmUgPC0gcmVhZC50YWJsZSgKICBmaWxlLnBhdGgoZGlyZWN0b3J5LCBkYXRhU2V0SWQsIHN1cHBsZW1lbnRhcnlfZmlsZXNbWzFdXSksCiAgICAgICAgICAgaGVhZGVyPVRSVUUsIAogICAgICAgICAgIGNoZWNrLm5hbWVzPVRSVUUKKQpkaW0oQUNUX3ZzX2Jhc2VsaW5lKQpgYGAKCjxicj4KPGJyPgpXZSBhbHNvIGVuc3VyZSB0aGF0IGFsbCBvZiB0aGUgZ2VuZXMgYW5kIHNhbXBsZXMgYXJlIHVuaXF1ZSBhbmQgdGhlcmUgYXJlIG5vIG51bGwgdmFsdWVzIGZvciBnZW5lcwpgYGB7cn0KI3VuaXF1ZSBzYW1wbGVzIQpsZW5ndGgodW5pcXVlKGNvbG5hbWVzKEFDVF92c19iYXNlbGluZSkpKSA9PSAyNgoKI3VuaXF1ZSBnZW5lcyEKbGVuZ3RoKHVuaXF1ZShyb3duYW1lcyhBQ1RfdnNfYmFzZWxpbmUpKSkgPT0gMTkxMTcKCiNubyBudWxsIHJvd3MgbmFtZXMhCmxlbmd0aCghaXMubmEocm93bmFtZXMoQUNUX3ZzX2Jhc2VsaW5lKSkpID09IDE5MTE3CmBgYAo8YnI+Cjxicj4KSGVyZSwgd2UgdmlzdWFsaXplIHRoZSBkb3dubG9hZGVkIGdlbmUgY291bnRzIGRhdGEgdGFibGUsIGZvciBhIHNtYWxsIHN1YnNldCBvZiB0aGUgZGF0YSAoNSBnZW5lcyBhbmQgMiBzYW1wbGVzIGZyb20gb25lIHBhdGllbnQpLiAKYGBge3J9CiNWaXN1YWxpemUgc3Vic2V0IG9mIHRoZSBkYXRhLiAKI2RhdGEgbWFrZXMgcGVyZmVjdCBzZW5zZSEgVGhhbmtzIGF1dGhvcnMhCkFDVF92c19iYXNlbGluZVsxOjUsIDE6Ml0KYGBgCgoKCiMjIyBNYXBwaW5nIHRvIEhVR08gR2VuZSBTeW1ib2xzCkFjY29yZGluZyB0byB0aGUgb3V0cHV0IG9mIG9uZSBvZiB0aGUgcHJldmlvdXMgY29kZSBibG9ja3MgYWJvdmUgaW4gdGhlICJEYXRhc2V0IEJhY2tncm91bmQgSW5mb3JtYXRpb24iIHNlY3Rpb24sIGFzIHdlbGwgYXMgYnkganVzdCBpbnNwZWN0aW5nIHRoZSBhYm92ZSBzdWJzZXQgb2YgZGF0YSwgb3VyIGdlbmUgZXhwcmVzc2lvbiBkYXRhIGhhcyBhbHJlYWR5IGJlZW4gbWFwcGVkIHRvIEhVR08gc3ltYm9scy4gSG93ZXZlciwgaXQgc3RpbGwgbWF5IGJlIG9mIGludGVyZXN0IHRvIHJlLW1hcCB0aGUgcm93bmFtZXMgdG8gSFVHTyBzeW1ib2xzIG91cnNlbHZlcyB0byBzZWUgaWYgdGhlcmUgYXJlIGFueSByb3dzIGluIG91ciBkYXRhIHRoYXQgY2Fubm90IGJlIG1hcHBlZCB0byBIVUdPIGdlbmUgc3ltYm9scy4gVGhlIGZvbGxvd2luZyBjb2RlIGJsb2NrcyBjb25uZWN0IHRvIGJpb01hcnQsIGFuZCBjcmVhdGUgYSBjb252ZXJzaW9uIGZpbGUgZm9yIG1hcHBpbmcgb3VyIGN1cnJlbnQgZ2VuZSBzeW1ib2xzIHRvIEhVR08gZ2VuZSBzeW1ib2xzLiAKYGBge3J9CiNjb25uZWN0IHRvIG1hcnQgKyB1c2UgdGhlIGh1bWFuIGRhdGFzZXQuCmVuc2VtYmwgPC0gdXNlTWFydCgiZW5zZW1ibCIpCmVuc2VtYmwgPSB1c2VEYXRhc2V0KCJoc2FwaWVuc19nZW5lX2Vuc2VtYmwiLCBtYXJ0PWVuc2VtYmwpCgpgYGAKCgpgYGB7cn0KY29udmVydElkcyA8LSByb3duYW1lcyhBQ1RfdnNfYmFzZWxpbmUpCgojY2hlY2sgdG8gc2VlIGlmIGNvbnZlcnNpb24gZmlsZSBleGlzdHMsIGlmIG5vdCwgY3JlYXRlIGl0LiAKY29udmVyc2lvbl9zdGFzaCA8LSAiaWRfY29udmVyc2lvbi5yZHMiCmlmKGZpbGUuZXhpc3RzKGNvbnZlcnNpb25fc3Rhc2gpKSB7CiAgaWRfY29udmVyc2lvbiA8LSByZWFkUkRTKGNvbnZlcnNpb25fc3Rhc2gpCn0gZWxzZSB7CiAgIyBhdHRyaWJ1dGVzIHJlZmVycyB0bzogd2hhdCBpZGVudGlmaWVyIHR5cGUgd2Ugd2FudCAoaW4gdGhpcyBjYXNlICJoZ25jX3N5bWJvbCIpCiAgIyBmaWx0ZXJzIHJlZmVycyB0bzogd2hhdCB3ZSB3aWxsIGZpbHRlciByZXN1bHRzIGJ5LCB3aGljaCBpcyBqdXN0ICJoZ25jX3N5bWJvbCIKICAjIHZhbHVlcyByZWZlcnMgdG86ICJoZ25jX3N5bWJvbCIgKFdoYXQgd2UgaGF2ZSBhcyByb3duYW1lcyBzbyBmYXIpCiAgaWRfY29udmVyc2lvbiA8LSBnZXRCTShhdHRyaWJ1dGVzID0gYygiaGduY19zeW1ib2wiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXJzID0gYygiaGduY19zeW1ib2wiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBjb252ZXJ0SWRzLCAKICAgICAgICAgICAgICAgICAgICAgICAgIG1hcnQgPSBlbnNlbWJsKQogIHNhdmVSRFMoaWRfY29udmVyc2lvbiwgY29udmVyc2lvbl9zdGFzaCkKfQoKCmBgYAo8YnI+Cjxicj4KSGVyZSwgd2Ugb3V0cHV0IHN0YXRpc3RpY3M6ICgxKSB0aGUgbnVtYmVyIG9mIGdlbmVzIGZyb20gb3VyIG9yaWdpbmFsIGdlbmUgY291bnRzIHRhYmxlIHRoYXQgd2VyZSBtYXBwZWQgdG8gYWN0dWFsIEhVR08gc3ltYm9scywgKDIpIEhvdyBtYW55IGdlbmVzIGRpZCB3ZSBiZWdpbiB3aXRoIGluIG91ciBvcmlnaW5hbCB0YWJsZSwgYW5kICgzKSBUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuICgxKSBhbmQgKDIpLiBGcm9tIHRoZXNlIHJlc3VsdHMsICoqd2Ugc2VlIHRoYXQgOTQwIGdlbmVzIGZyb20gb3VyIG9yaWdpbmFsIGdlbmUgZXhwcmVzc2lvbiB0YWJsZSB3ZXJlIHVuYWJsZSB0byBiZSBtYXBwZWQgdG8gSFVHTyBnZW5lIHN5bWJvbHMuKiogVGhpcyBpcyBhY3R1YWxseSBub3QgdGhhdCBiYWQhIEluIGFkZGl0aW9uLCAqKnRoZXJlIGRvZXMgbm90IHNlZW0gdG8gYmUgZXhwcmVzc2lvbiB2YWx1ZXMgdGhhdCB3ZXJlIG5vdCB1bmlxdWUgZm9yIHNwZWNpZmljIGdlbmVzKiouIApgYGB7cn0KCiNob3cgbWFueSBnZW5lcyBmcm9tIG91ciBvcmlnaW5hbCBnZW5lIHN5bWJvbCByb3duYW1lcyB3ZXJlIG1hcHBlZCB0byBhY3R1YWwgSFVHTyBzeW1ib2xzPyAKbGVuZ3RoKHdoaWNoKHJvd25hbWVzKEFDVF92c19iYXNlbGluZSkgJWluJQogICAgICAgICAgICAgICBpZF9jb252ZXJzaW9uJGhnbmNfc3ltYm9sKSkKCiNPdXQgb2Ygb3VyIHRvdGFsIGdlbmVzIHRoYXQgd2Ugc3RhcnRlZCB3aXRoOiAKbnJvdyhBQ1RfdnNfYmFzZWxpbmUpCgojIENhbGN1bGF0ZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBudW1iZXIgb2Ygcm93cyBvcmlnaW5hbGx5IGFuZCB0aGVuIG51bWJlciBvZiByb3duYW1lcyB0aGF0IHdlcmUgYWJsZSB0byBiZSBtYXBwZWQgdG8gSFVHTyBzeW1ib2xzLiAKZGlmZmVyZW5jZU1hcCA8LSBucm93KEFDVF92c19iYXNlbGluZSkgLSBsZW5ndGgod2hpY2gocm93bmFtZXMoQUNUX3ZzX2Jhc2VsaW5lKSAlaW4lIGlkX2NvbnZlcnNpb24kaGduY19zeW1ib2wpKQoKZGlmZmVyZW5jZU1hcApgYGAKCjxicj4KPGJyPgpUaGlzIGNvZGUgYmxvY2sganVzdCBzaG93cyB0aGUgZmlyc3QgMTAgZ2VuZSBuYW1lcyAoZnJvbSB0aGUgOTQwIGNvdW50IGFib3ZlKSB0aGF0IHdlcmUgdW5hYmxlIHRvIGJlIG1hcHBlZCB0byBIVUdPIGdlbmUgc3ltYm9scy4gCmBgYHtyfQpyb3duYW1lcyhBQ1RfdnNfYmFzZWxpbmUpWyEocm93bmFtZXMoQUNUX3ZzX2Jhc2VsaW5lKSAlaW4lIGlkX2NvbnZlcnNpb24kaGduY19zeW1ib2wpXVsxOjEwXQpgYGAKPGJyPgo8YnI+CkluIHRoaXMgY29kZSBibG9jayBoZXJlLCBJIGRlY2lkZWQgdG8gbWVyZ2UgYm90aCB0aGUgaWRfY29udmVyc2lvbiBkYXRhIGZyYW1lICh3aXRoIHRoZSBhY3R1YWwgSFVHTyBnZW5lIHN5bWJvbHMpIGFuZCB0aGUgb3JpZ2luYWwgQUNUX3ZzX2Jhc2VsaW5lIGdlbmUgZXhwcmVzc2lvbiBkYXRhIGZyYW1lLiBUaGUgcmVzdWx0aW5nIGRhdGFmcmFtZSBzdGlsbCBrZWVwcyB0aGUgcm93cyB0aGF0IHdlcmUgdW5hYmxlIHRvIGJlIG1hcHBlZCB0byBIVUdPIGdlbmUgc3ltYm9scywgc2luY2UgdGhlc2UgZ2VuZXMgY291bGQgcG90ZW50aWFsbHkgY29uc3RpdHV0ZSBhbiB1bmNoYXJhY3Rlcml6ZWQgc2lnbmFsIGxhdGVyIG9uIGluIHRoZSByZXN0IG9mIHRoZSBhc3NpZ25tZW50cyAod2hlbiBwZXJmb3JtaW5nIERpZmZlcmVudGlhbCBFeHByZXNzaW9uIGFuZCBQYXRod2F5IGFuYWx5c2VzKS4gCmBgYHtyfQpBQ1RfdnNfYmFzZWxpbmVfYW5ub3QgPC0gbWVyZ2UoaWRfY29udmVyc2lvbiwgQUNUX3ZzX2Jhc2VsaW5lLCBieS54ID0gMSwgYnkueSA9IDAsIGFsbC55ID0gVFJVRSkKCnJvd25hbWVzKEFDVF92c19iYXNlbGluZV9hbm5vdCkgPC0gQUNUX3ZzX2Jhc2VsaW5lX2Fubm90JGhnbmNfc3ltYm9sCkFDVF92c19iYXNlbGluZV9hbm5vdCA8LSBBQ1RfdnNfYmFzZWxpbmVfYW5ub3RbLWMoMSldCgojIG91ciBjdXJyZW50IGdlbmUgY291bnRzIGRhdGEgdGFibGUgKHdpdGggbWFwcGluZyBjb21wbGV0ZWQpCkFDVF92c19iYXNlbGluZV9hbm5vdFsxOjEwLCAxOjJdCgoKYGBgCiMjIyBEYXRhc2V0IEZpbHRlcmF0aW9uIGFuZCBOb3JtYWxpemF0aW9uIApOb3cgdGhhdCB3ZSBoYXZlIHRoZSBnZW5lIGV4cHJlc3Npb24gY291bnRzIHRhYmxlIHdpdGggSFVHTyBnZW5lIHN5bWJvbCBtYXBwaW5ncywgdGhlIG5leHQgc3RlcCBpcyB0byBmaWx0ZXIgb3V0IHRoZSBnZW5lcyB3aXRoIGxvdyBjb3VudHMgYW5kIG5vcm1hbGl6ZSBvdXIgZGF0YS4gRmlsdGVyaW5nIGVuc3VyZXMgdGhhdCB0aGVyZSBpcyBsZXNzIG5vaXNlIGluIHRoZSBkYXRhLCBhbmQgc3RhdGlzdGljYWwgY2FsY3VsYXRpb25zIGFyZSBsZXNzIGNvbXB1dGF0aW9uYWxseSBpbnRlbnNpdmUgZG93biB0aGUgbGluZSAoc2luY2Ugd2Ugd2lsbCBoYXZlIGxlc3MgZ2VuZXMpLiBTYW1wbGUgYmFzZWQgbm9ybWFsaXphdGlvbiBlbnN1cmVzIHRvIGFkanVzdCBmb3IgdmFyaWF0aW9ucyBpbiB0aGUgZGF0YSBhbmQgYWxzbyBhbGxvd3MgZm9yIGJldHdlZW4gc2FtcGxlIGNvbXBhcmlzb25zLiBUaGUgZmlyc3QgY29kZSBibG9jayBvdXRwdXRzIGEgZGVuc2l0eSBwbG90IG9mIHRoZSBnZW5lIGV4cHJlc3Npb24gZGF0YSBCRUZPUkUgZmlsdHJhdGlvbiBhbmQgbm9ybWFsaXphdGlvbi4gClRoZSBuZXh0IGNvdXBsZSBvZiBjb2RlIGJsb2NrcyBhZnRlciwgZmlsdGVycyBvdXQgdGhlIGdlbmVzIHdpdGggbG93IGNvdW50cywgYW5kIHBlcmZvcm1zIFRNTSBub3JtYWxpemF0aW9uLiAKCmBgYHtyfQojIGRlbnNpdHkgZ3JhcGggcHJlIGZpbHRlcmluZyArIHByZSBub3JtYWxpemF0aW9uCmNvdW50c19kZW5zaXR5IDwtIGFwcGx5KGxvZzIoQUNUX3ZzX2Jhc2VsaW5lX2Fubm90KSwgMiwgZGVuc2l0eSkKeGxpbSA8LSAwOyB5bGltIDwtIDAKZm9yIChpIGluIDE6bGVuZ3RoKGNvdW50c19kZW5zaXR5KSkgewogIHhsaW0gPC0gcmFuZ2UoYyh4bGltLCBjb3VudHNfZGVuc2l0eVtbaV1dJHgpKTsKICB5bGltIDwtIHJhbmdlKGMoeWxpbSwgY291bnRzX2RlbnNpdHlbW2ldXSR5KSkKfQoKY29scyA8LSAobGVuZ3RoKGNvdW50c19kZW5zaXR5KSkKbHR5cyA8LSByZXAoMSwgbGVuZ3RoKGNvdW50c19kZW5zaXR5KSkKCiNwbG90IApwbG90KGNvdW50c19kZW5zaXR5W1sxXV0sIHhsaW09eGxpbSwgeWxpbT15bGltLCB0eXBlPSJuIiwgCiAgICAgeWxhYj0iU21vb3RoaW5nIGRlbnNpdHkgb2YgbG9nMi1DUE0iLCAKICAgICBtYWluPSIiLCBjZXgubGFiID0gMC44NSkKCmZvcihpIGluIDE6bGVuZ3RoKGNvdW50c19kZW5zaXR5KSkKICBsaW5lcyhjb3VudHNfZGVuc2l0eVtbaV1dLCBjb2xzPWNvbHNbaV0sIGx0eT1sdHlzW2ldKQoKYGBgCgoqKldlIHNlZSBoZXJlIHRoYXQgdGhlIGZpbHRlcmF0aW9uIG9mIG91dGxpZXIgZ2VuZXMgd2l0aCBsb3cgZ2VuZSBjb3VudHMsIHJlbW92ZWQgMzY3OCBnZW5lcyBmcm9tIG91ciBleHByZXNzaW9uIGRhdGFzZXQqKgpgYGB7cn0KCiMgc2V0IHRoZSBtaW5pbXVtIG51bWJlciBvZiBzYW1wbGVzCm1pbl9zYW1wbGVzIDwtIDMKCmRhdGFfYXNfbWF0cml4IDwtIGFzLm1hdHJpeChBQ1RfdnNfYmFzZWxpbmVfYW5ub3QpCgojIEZpbHRlciBvdXQgbG93IGNvdW50cwprZWVwIDwtIHJvd1N1bXMoY3BtKGRhdGFfYXNfbWF0cml4KSA+IDEpID49IG1pbl9zYW1wbGVzCmRhdGFfZmlsdGVyZWQgPC0gZGF0YV9hc19tYXRyaXhba2VlcCxdCm5yb3coZGF0YV9maWx0ZXJlZCkKCiNUb3RhbCBudW1iZXIgb2YgZ2VuZXMgcmVtb3ZlZDogCm5yb3coQUNUX3ZzX2Jhc2VsaW5lX2Fubm90KSAtIG5yb3coZGF0YV9maWx0ZXJlZCkKYGBgCgpgYGB7cn0KCiMgVE1NIE5vcm1hbGl6YXRpb24gCmRnZV9saXN0ID0gREdFTGlzdChjb3VudHMgPSBkYXRhX2ZpbHRlcmVkKQpkZ2VfbGlzdCA9IGNhbGNOb3JtRmFjdG9ycyhkZ2VfbGlzdCkKbm9ybWFsaXplZF9jb3VudHMgPC0gY3BtKGRnZV9saXN0KQpub3JtYWxpemVkX2NvdW50cyA8LSBhcy5kYXRhLmZyYW1lKG5vcm1hbGl6ZWRfY291bnRzKQoKbm9ybWFsaXplZF9jb3VudHMKCgpgYGAKPGJyPgo8YnI+ClRoaXMgY29kZSBibG9jayBvdXRwdXRzIGEgZGVuc2l0eSBwbG90IG9mIHRoZSBnZW5lIGV4cHJlc3Npb24gZGF0YSBhZnRlciBmaWx0cmF0aW9uIGFuZCBub3JtYWxpemF0aW9uLiBDb21wYXJpbmcgdGhlIHR3byBwbG90cyAocHJlLSBhbmQgcG9zdC0gZmlsdGVyYXRpb24gKyBub3JtYWxpemF0aW9uKSwgc2hvd3MgdGhlIGNoYW5nZXMgaW4gdGhlIGRhdGEsIHVuaWZvcm0gYW5kIGxlc3Mgbm9pc3kuIApgYGB7cn0KI3Bvc3QtZmlsdGVyaW5nICsgcG9zdCBub3JtYWxpemF0aW9uOiAKCmNvdW50c19kZW5zaXR5IDwtIGFwcGx5KGxvZzIobm9ybWFsaXplZF9jb3VudHMpLCAyLCBkZW5zaXR5KQp4bGltIDwtIDA7IHlsaW0gPC0gMApmb3IgKGkgaW4gMTpsZW5ndGgoY291bnRzX2RlbnNpdHkpKSB7CiAgeGxpbSA8LSByYW5nZShjKHhsaW0sIGNvdW50c19kZW5zaXR5W1tpXV0keCkpOwogIHlsaW0gPC0gcmFuZ2UoYyh5bGltLCBjb3VudHNfZGVuc2l0eVtbaV1dJHkpKQp9Cgpjb2xzIDwtIChsZW5ndGgoY291bnRzX2RlbnNpdHkpKQpsdHlzIDwtIHJlcCgxLCBsZW5ndGgoY291bnRzX2RlbnNpdHkpKQoKI3Bsb3QgCnBsb3QoY291bnRzX2RlbnNpdHlbWzFdXSwgeGxpbT14bGltLCB5bGltPXlsaW0sIHR5cGU9Im4iLCAKICAgICB5bGFiPSJTbW9vdGhpbmcgZGVuc2l0eSBvZiBsb2cyLUNQTSIsIAogICAgIG1haW49IiIsIGNleC5sYWIgPSAwLjg1KQoKZm9yKGkgaW4gMTpsZW5ndGgoY291bnRzX2RlbnNpdHkpKQogIGxpbmVzKGNvdW50c19kZW5zaXR5W1tpXV0sIGNvbHM9Y29sc1tpXSwgbHR5PWx0eXNbaV0pCgpgYGAKPGJyPgo8YnI+ClRoZSBsYXN0IHN0ZXAgb2YgdGhpcyBub3RlYm9vayBpcyB0byBleHBvcnQgb3V0IG91ciBmdWxseSBwcm9jZXNzZWQgKG1hcHBlZCwgZmlsdGVyZWQsIGFuZCBub3JtYWxpemVkKSBnZW5lIGV4cHJlc3Npb24gZGF0YWZyYW1lIHRvIGEgdHh0IGZpbGUgZm9yIGRvd25zdHJlYW0gdXNlIGluIGZ1dHVyZSBhc3NpZ25tZW50cyEgKipJbiByZWdhcmRzIHRvIHRoZSBmaW5hbCBjb3ZlcmFnZSBvZiBteSBkYXRhc2V0LCB0aGUgZW5kIHByb2R1Y3QgaXMgYSBkYXRhZnJhbWUgd2l0aCAxNTQzOSBIVUdPIG1hcHBlZCBnZW5lcyBhbmQgY291bnRzIGZvciBlYWNoKioKYGBge3J9CndyaXRlLnRhYmxlKG5vcm1hbGl6ZWRfY291bnRzLCBmaWxlLnBhdGgoZ2V0d2QoKSwibm9ybWFsaXplZF9iYXNlbGluZV92c19USUxfY291bnRzLnR4dCIpLCBxdW90ZSA9IEZBTFNFLCBzZXAgPSAiXHQiLCByb3cubmFtZXMgPSBUUlVFKQpgYGAKCiMjIyBSZWZlcmVuY2VzCgogIE1vcmdhbiBNLCBSYW1vcyBNICgyMDIzKS4gX0Jpb2NNYW5hZ2VyOiBBY2Nlc3MgdGhlIEJpb2NvbmR1Y3RvciBQcm9qZWN0IFBhY2thZ2UKICAgICAgUmVwb3NpdG9yeV8uIFIgcGFja2FnZSB2ZXJzaW9uIDEuMzAuMjIsCiAgICAgIDxodHRwczovL0NSQU4uUi1wcm9qZWN0Lm9yZy9wYWNrYWdlPUJpb2NNYW5hZ2VyPi4KICAgICAgCiAgRGF2aXMsIFMuIGFuZCBNZWx0emVyLCBQLiBTLiBHRU9xdWVyeTogYSBicmlkZ2UgYmV0d2VlbiB0aGUgR2VuZSBFeHByZXNzaW9uCiAgICAgIE9tbmlidXMgKEdFTykgYW5kIEJpb0NvbmR1Y3Rvci4gQmlvaW5mb3JtYXRpY3MsIDIwMDcsIDE0LCAxODQ2LTE4NDcKICAgICAgCiAgWGllIFkgKDIwMjMpLiBfa25pdHI6IEEgR2VuZXJhbC1QdXJwb3NlIFBhY2thZ2UgZm9yIER5bmFtaWMgUmVwb3J0IEdlbmVyYXRpb24gaW4KICAgICAgUl8uIFIgcGFja2FnZSB2ZXJzaW9uIDEuNDUsIDxodHRwczovL3lpaHVpLm9yZy9rbml0ci8+LgogICAgICAKICBSb2JpbnNvbiBNRCwgTWNDYXJ0aHkgREogYW5kIFNteXRoIEdLICgyMDEwKS4gZWRnZVI6IGEgQmlvY29uZHVjdG9yIHBhY2thZ2UgZm9yCiAgICAgIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIG9mIGRpZ2l0YWwgZ2VuZSBleHByZXNzaW9uIGRhdGEuIEJpb2luZm9ybWF0aWNzCiAgICAgIDI2LCAxMzktMTQwCiAgICAgIApSZXNwb25zZSB0byB0dW1vci1pbmZpbHRyYXRpbmcgbHltcGhvY3l0ZSBhZG9wdGl2ZSB0aGVyYXB5IGlzIGFzc29jaWF0ZWQgd2l0aCBwcmVleGlzdGluZyAKICAgICBDRDgrIFQtbXllbG9pZCBjZWxsIC4uLiAobi5kLikuIDxodHRwczovL3d3dy5zY2llbmNlLm9yZy9kb2kvMTAuMTEyNi9zY2lpbW11bm9sLmFkZzc5OTU+IAogIAogICAgICAKICAKCgo=